class Cargo < ActiveRecord::Base

  default_scope :order => :nombre
  named_scope :activos,:conditions=>{:deleted_at=>nil}
  belongs_to :area
  belongs_to :nivel

  has_many :usuarios
  has_many :preguntas
  has_many :tareas

  has_many :superiores
  has_many :pares
  has_many :subordinados
  has_many :competencias_cargos
  has_many :competencias, :through => :competencias_cargos
  has_and_belongs_to_many :factores_reconocimientos,:join_table => 'cargos_factores_reconocimientos'#,:foreign_key=>:cargo_id
  
  validates_presence_of   :nombre
  validates_uniqueness_of :nombre

  

  def competencias_all
    competencias + Competencia.all(:conditions => {:tipo => 'general'})
  end

  def competencias_all_ids
    competencias.map(&:id) + Competencia.all(:conditions => {:tipo => 'general'}).map(&:id)
  end
  
  def autoevaluacion?
    !!Par.find_cargo_autoevaluacion(self)
  end

  def update_jerarquias(jerarquias)
    update_subordinados(jerarquias[:subordinados])
    update_pares(jerarquias[:pares])
    update_superiores(jerarquias[:superiores])
  end

  def cargos_subordinados(filter = nil)
    area = "AND area_id = #{area_id}" if self.area_id && filter
    Cargo.find_by_sql(
      <<-SQL
     SELECT DISTINCT cargos.* FROM cargos
     JOIN subordinados ON cargos.id = subordinados.subordinado_id
     WHERE cargos.id <> #{self.id} AND subordinados.cargo_id = #{self.id} #{area}
      SQL
    )
  end

  def cargos_pares(filter = nil)
    area = "AND area_id = #{area_id}" if self.area_id && filter
    Cargo.find_by_sql(
      <<-SQL
     SELECT DISTINCT cargos.* FROM cargos
     JOIN pares ON  cargos.id = pares.par_id
     WHERE pares.es_autoevaluacion = 0 AND pares.cargo_id = #{self.id} #{area}
      SQL
    )
  end

  def cargos_superiores(filter = nil)
    area = "AND area_id = #{area_id}" if self.area_id && filter
    Cargo.find_by_sql(
      <<-SQL
     SELECT DISTINCT cargos.* FROM cargos
     JOIN superiores ON cargos.id = superiores.superior_id
     WHERE cargos.id <> #{self.id} AND superiores.cargo_id = #{self.id} #{area}
      SQL
    )
  end

  #Campos para el ajaxpopup
  attr_writer :area_nombre, :supervisa_nombre, :reporta_nombre
  delegate :nombre, :to => :area, :prefix => true, :allow_nil => true
  def reporta_nombre
    self.reporta.try(:nombre)
  end

  def supervisa_nombre
    self.supervisa.try(:nombre)
  end


  def update_subordinados(subordinados)
    self.subordinados  = []
    unless subordinados.empty?
      subordinados.split(' ').each do |subordinado_id|
        #buscamos relacion
        self.delete_relation(subordinado_id)
        Subordinado.create(:cargo_id => self.id, :subordinado_id => subordinado_id)
        Superior.create(:cargo_id => subordinado_id, :superior_id => self.id)
      end
    else
      self.subordinados.map(&:destroy)
    end
  end

  def update_pares(pares_array)
    self.pares.sin_autoevaluacion.map(&:destroy)
    unless pares_array.empty?
      pares_array.split(' ').each do |par_id|
        self.delete_relation(par_id)
        Par.create(:cargo_id => par_id,  :par_id => self.id)
        Par.create(:cargo_id => self.id, :par_id => par_id) unless par_id == self.id
      end
    else
      self.pares.sin_autoevaluacion.map(&:destroy)
    end
  end

  def update_superiores(superiores)
    self.superiores  = []
    unless superiores.empty?
      superiores.split(' ').each do |superior_id|
        self.delete_relation(superior_id)
        Superior.create(:cargo_id    => self.id, :superior_id => superior_id)
        Subordinado.create(:cargo_id => superior_id, :subordinado_id => self.id)
      end
    else
      self.superiores.map(&:destroy)
    end
  end


  def delete_relation(jerarquia_id)
    jerarquia_id = jerarquia_id.to_i
    cargos_subordinados_ids, cargos_pares_ids, cargos_superiores_ids = jerarquias_ids
    
    if cargos_subordinados_ids.include?(jerarquia_id)
      #borrar subordinado
      Subordinado.find(:first, :conditions => ["cargo_id = ? AND subordinado_id = ?", self.id, jerarquia_id]).try(:destroy)
      Superior.find(:first,    :conditions => ["cargo_id = ? AND superior_id = ?", jerarquia_id, self.id]).try(:destroy)
    elsif cargos_superiores_ids.include?(jerarquia_id)
      Subordinado.find(:first, :conditions => ["cargo_id = ? AND subordinado_id = ?", jerarquia_id, self.id]).try(:destroy)
      Superior.find(:first,    :conditions => ["cargo_id = ? AND superior_id = ?", self.id, jerarquia_id]).try(:destroy)
    elsif cargos_pares_ids.include?(jerarquia_id)
      Par.find(:first, :conditions => ["cargo_id = ? AND par_id = ? AND es_autoevaluacion = 0", self.id, jerarquia_id]).try(:destroy)
      Par.find(:first, :conditions => ["cargo_id = ? AND par_id = ? AND es_autoevaluacion = 0", jerarquia_id, self.id]).try(:destroy)
    end
  end
  
  def todos_subordinados
    cargos = []
    lista_cargos = self.cargos_subordinados
    lista_cargos.each do |c|
      cargos += c.todos_subordinados
    end
    cargos.uniq + lista_cargos.map(&:id)
  end

  def jerarquias_ids
    subordinados_ids = self.cargos_subordinados.map(&:id) # [7,8]
    pares_ids        = self.cargos_pares.map(&:id) # [3,4]
    superiores_ids   = self.cargos_superiores.map(&:id) # [9,10]
    [subordinados_ids, pares_ids, superiores_ids]
  end

  def area_nombre
    area.nombre if area
  end

  def destroy
    deleted_at=Time.now
    save
  end
end

